{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyN/NH8yBU+BCOBBW8UzlzQa",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/tomasonjo/blogs/blob/master/llm/graphreader.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Az8JvO0tmR9h",
        "outputId": "f36037f7-b6e8-4e0b-cefa-50b54bf2229b"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/52.0 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.0/52.0 kB\u001b[0m \u001b[31m1.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/362.9 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m362.9/362.9 kB\u001b[0m \u001b[31m10.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m26.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m318.9/318.9 kB\u001b[0m \u001b[31m15.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "!pip install --quiet neo4j langchain-community langchain-core langchain-openai"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import os\n",
        "import getpass\n",
        "from langchain_core.prompts import ChatPromptTemplate\n",
        "\n",
        "from langchain_openai import ChatOpenAI\n",
        "from langchain_core.pydantic_v1 import BaseModel, Field\n",
        "\n",
        "from typing import List\n",
        "\n",
        "from hashlib import md5\n"
      ],
      "metadata": {
        "id": "QgQQ5YRFoc2O"
      },
      "execution_count": 29,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")"
      ],
      "metadata": {
        "id": "QpCb9N75pSb1"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "construction_system = \"\"\"\n",
        "You are now an intelligent assistant tasked with meticulously extracting both key elements and\n",
        "atomic facts from a long text.\n",
        "1. Key Elements: The essential nouns (e.g., characters, times, events, places, numbers), verbs (e.g.,\n",
        "actions), and adjectives (e.g., states, feelings) that are pivotal to the text’s narrative.\n",
        "2. Atomic Facts: The smallest, indivisible facts, presented as concise sentences. These include\n",
        "propositions, theories, existences, concepts, and implicit elements like logic, causality, event\n",
        "sequences, interpersonal relationships, timelines, etc.\n",
        "Requirements:\n",
        "#####\n",
        "1. Ensure that all identified key elements are reflected within the corresponding atomic facts.\n",
        "2. You should extract key elements and atomic facts comprehensively, especially those that are\n",
        "important and potentially query-worthy and do not leave out details.\n",
        "3. Whenever applicable, replace pronouns with their specific noun counterparts (e.g., change I, He,\n",
        "She to actual names).\n",
        "4. Ensure that the key elements and atomic facts you extract are presented in the same language as\n",
        "the original text (e.g., English or Chinese).\n",
        "\"\"\""
      ],
      "metadata": {
        "id": "M8ZpVz7XmaMz"
      },
      "execution_count": 10,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "construction_prompt = ChatPromptTemplate.from_messages(\n",
        "    [\n",
        "        (\n",
        "            \"system\",\n",
        "            construction_system,\n",
        "        ),\n",
        "        (\n",
        "            \"human\",\n",
        "            (\n",
        "                \"Use the given format to extract information from the \"\n",
        "                \"following input: {input}\"\n",
        "            ),\n",
        "        ),\n",
        "    ]\n",
        ")"
      ],
      "metadata": {
        "id": "lV3DgZfvpjk1"
      },
      "execution_count": 11,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "class AtomicFact(BaseModel):\n",
        "    key_elements: List[str] = Field(description=\"\"\"The essential nouns (e.g., characters, times, events, places, numbers), verbs (e.g.,\n",
        "actions), and adjectives (e.g., states, feelings) that are pivotal to the atomic fact's narrative.\"\"\")\n",
        "    atomic_fact: str = Field(description=\"\"\"The smallest, indivisible facts, presented as concise sentences. These include\n",
        "propositions, theories, existences, concepts, and implicit elements like logic, causality, event\n",
        "sequences, interpersonal relationships, timelines, etc.\"\"\")\n",
        "\n",
        "class Extraction(BaseModel):\n",
        "    atomic_facts: List[AtomicFact] = Field(description=\"List of atomic facts\")\n",
        "\n",
        "\n",
        "model = ChatOpenAI(model=\"gpt-4o\", temperature=0.3)\n",
        "structured_llm = model.with_structured_output(Extraction)"
      ],
      "metadata": {
        "id": "nG3PAV8xnc9Z"
      },
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "construction_chain = construction_prompt | structured_llm"
      ],
      "metadata": {
        "id": "wqz316TGp4C2"
      },
      "execution_count": 19,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "text = \"\"\"Joan of Arc (French: Jeanne d'Arc [ʒan daʁk]; Middle French: Jehanne Darc [ʒəˈãnə ˈdark]; c. 1412 – 30 May 1431) is a patron saint of France, honored as a defender of the French nation for her role in the siege of Orléans and her insistence on the coronation of Charles VII of France during the Hundred Years' War. Claiming to be acting under divine guidance, she became a military leader who transcended gender roles and gained recognition as a savior of France.\n",
        "\n",
        "Joan was born to a propertied peasant family at Domrémy in northeast France. In 1428, she requested to be taken to Charles VII, later testifying that she was guided by visions from the archangel Michael, Saint Margaret, and Saint Catherine to help him save France from English domination. Convinced of her devotion and purity, Charles sent Joan, who was about seventeen years old, to the siege of Orléans as part of a relief army. She arrived at the city in April 1429, wielding her banner and bringing hope to the demoralized French army. Nine days after her arrival, the English abandoned the siege. Joan encouraged the French to aggressively pursue the English during the Loire Campaign, which culminated in another decisive victory at Patay, opening the way for the French army to advance on Reims unopposed, where Charles was crowned as the King of France with Joan at his side. These victories boosted French morale, paving the way for their final triumph in the Hundred Years' War several decades later.\n",
        "\n",
        "After Charles's coronation, Joan participated in the unsuccessful siege of Paris in September 1429 and the failed siege of La Charité in November. Her role in these defeats reduced the court's faith in her. In early 1430, Joan organized a company of volunteers to relieve Compiègne, which had been besieged by the Burgundians—French allies of the English. She was captured by Burgundian troops on 23 May. After trying unsuccessfully to escape, she was handed to the English in November. She was put on trial by Bishop Pierre Cauchon on accusations of heresy, which included blaspheming by wearing men's clothes, acting upon visions that were demonic, and refusing to submit her words and deeds to the judgment of the church. She was declared guilty and burned at the stake on 30 May 1431, aged about nineteen.\"\"\"\n",
        "result = construction_chain.invoke({\"input\":text})\n",
        "print(result)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "f8XzROIKp7hL",
        "outputId": "828909ab-8035-45a9-e06a-6fda9de7d452"
      },
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "atomic_facts=[AtomicFact(key_elements=['Joan of Arc', 'French', \"Jeanne d'Arc\", 'Middle French', 'Jehanne Darc', '1412', '30 May 1431', 'patron saint', 'France', 'defender', 'French nation', 'siege of Orléans', 'coronation', 'Charles VII', \"Hundred Years' War\"], atomic_fact=\"Joan of Arc (French: Jeanne d'Arc; Middle French: Jehanne Darc; c. 1412 – 30 May 1431) is a patron saint of France, honored as a defender of the French nation for her role in the siege of Orléans and her insistence on the coronation of Charles VII of France during the Hundred Years' War.\"), AtomicFact(key_elements=['Joan of Arc', 'divine guidance', 'military leader', 'gender roles', 'savior', 'France'], atomic_fact='Claiming to be acting under divine guidance, Joan of Arc became a military leader who transcended gender roles and gained recognition as a savior of France.'), AtomicFact(key_elements=['Joan of Arc', 'propertied peasant family', 'Domrémy', 'northeast France'], atomic_fact='Joan of Arc was born to a propertied peasant family at Domrémy in northeast France.'), AtomicFact(key_elements=['Joan of Arc', '1428', 'Charles VII', 'visions', 'archangel Michael', 'Saint Margaret', 'Saint Catherine', 'save France', 'English domination'], atomic_fact='In 1428, Joan of Arc requested to be taken to Charles VII, later testifying that she was guided by visions from the archangel Michael, Saint Margaret, and Saint Catherine to help him save France from English domination.'), AtomicFact(key_elements=['Charles VII', 'devotion', 'purity', 'Joan of Arc', 'seventeen years old', 'siege of Orléans', 'relief army'], atomic_fact='Convinced of her devotion and purity, Charles VII sent Joan of Arc, who was about seventeen years old, to the siege of Orléans as part of a relief army.'), AtomicFact(key_elements=['Joan of Arc', 'April 1429', 'banner', 'hope', 'French army', 'demoralized'], atomic_fact='Joan of Arc arrived at the city in April 1429, wielding her banner and bringing hope to the demoralized French army.'), AtomicFact(key_elements=['Joan of Arc', 'nine days', 'arrival', 'English', 'abandoned', 'siege'], atomic_fact=\"Nine days after Joan of Arc's arrival, the English abandoned the siege.\"), AtomicFact(key_elements=['Joan of Arc', 'French', 'aggressively pursue', 'English', 'Loire Campaign', 'decisive victory', 'Patay', 'French army', 'advance', 'Reims', 'unopposed', 'Charles VII', 'crowned', 'King of France', 'Joan of Arc', 'side'], atomic_fact='Joan of Arc encouraged the French to aggressively pursue the English during the Loire Campaign, which culminated in another decisive victory at Patay, opening the way for the French army to advance on Reims unopposed, where Charles VII was crowned as the King of France with Joan of Arc at his side.'), AtomicFact(key_elements=['victories', 'French morale', 'final triumph', \"Hundred Years' War\", 'several decades later'], atomic_fact=\"These victories boosted French morale, paving the way for their final triumph in the Hundred Years' War several decades later.\"), AtomicFact(key_elements=[\"Charles VII's coronation\", 'Joan of Arc', 'unsuccessful', 'siege of Paris', 'September 1429', 'failed', 'siege of La Charité', 'November'], atomic_fact=\"After Charles VII's coronation, Joan of Arc participated in the unsuccessful siege of Paris in September 1429 and the failed siege of La Charité in November.\"), AtomicFact(key_elements=['defeats', \"court's faith\", 'Joan of Arc', 'reduced'], atomic_fact=\"Her role in these defeats reduced the court's faith in Joan of Arc.\"), AtomicFact(key_elements=['early 1430', 'Joan of Arc', 'company of volunteers', 'relieve', 'Compiègne', 'besieged', 'Burgundians', 'French allies', 'English'], atomic_fact='In early 1430, Joan of Arc organized a company of volunteers to relieve Compiègne, which had been besieged by the Burgundians—French allies of the English.'), AtomicFact(key_elements=['Joan of Arc', 'captured', 'Burgundian troops', '23 May'], atomic_fact='Joan of Arc was captured by Burgundian troops on 23 May.'), AtomicFact(key_elements=['Joan of Arc', 'unsuccessfully', 'escape', 'handed', 'English', 'November'], atomic_fact='After trying unsuccessfully to escape, Joan of Arc was handed to the English in November.'), AtomicFact(key_elements=['Joan of Arc', 'trial', 'Bishop Pierre Cauchon', 'heresy', 'blaspheming', \"wearing men's clothes\", 'visions', 'demonic', 'refusing', 'submit', 'judgment', 'church'], atomic_fact=\"Joan of Arc was put on trial by Bishop Pierre Cauchon on accusations of heresy, which included blaspheming by wearing men's clothes, acting upon visions that were demonic, and refusing to submit her words and deeds to the judgment of the church.\"), AtomicFact(key_elements=['Joan of Arc', 'guilty', 'burned at the stake', '30 May 1431', 'nineteen years old'], atomic_fact='Joan of Arc was declared guilty and burned at the stake on 30 May 1431, aged about nineteen.')]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "result.dict()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "lzQ_S4rP1BDN",
        "outputId": "1fc89591-1c53-44f2-b03e-cab12a45abeb"
      },
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'atomic_facts': [{'key_elements': ['Joan of Arc',\n",
              "    'French',\n",
              "    \"Jeanne d'Arc\",\n",
              "    'Middle French',\n",
              "    'Jehanne Darc',\n",
              "    '1412',\n",
              "    '30 May 1431',\n",
              "    'patron saint',\n",
              "    'France',\n",
              "    'defender',\n",
              "    'French nation',\n",
              "    'siege of Orléans',\n",
              "    'coronation',\n",
              "    'Charles VII',\n",
              "    \"Hundred Years' War\"],\n",
              "   'atomic_fact': \"Joan of Arc (French: Jeanne d'Arc; Middle French: Jehanne Darc; c. 1412 – 30 May 1431) is a patron saint of France, honored as a defender of the French nation for her role in the siege of Orléans and her insistence on the coronation of Charles VII of France during the Hundred Years' War.\"},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'divine guidance',\n",
              "    'military leader',\n",
              "    'gender roles',\n",
              "    'savior',\n",
              "    'France'],\n",
              "   'atomic_fact': 'Claiming to be acting under divine guidance, Joan of Arc became a military leader who transcended gender roles and gained recognition as a savior of France.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'propertied peasant family',\n",
              "    'Domrémy',\n",
              "    'northeast France'],\n",
              "   'atomic_fact': 'Joan of Arc was born to a propertied peasant family at Domrémy in northeast France.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    '1428',\n",
              "    'Charles VII',\n",
              "    'visions',\n",
              "    'archangel Michael',\n",
              "    'Saint Margaret',\n",
              "    'Saint Catherine',\n",
              "    'save France',\n",
              "    'English domination'],\n",
              "   'atomic_fact': 'In 1428, Joan of Arc requested to be taken to Charles VII, later testifying that she was guided by visions from the archangel Michael, Saint Margaret, and Saint Catherine to help him save France from English domination.'},\n",
              "  {'key_elements': ['Charles VII',\n",
              "    'devotion',\n",
              "    'purity',\n",
              "    'Joan of Arc',\n",
              "    'seventeen years old',\n",
              "    'siege of Orléans',\n",
              "    'relief army'],\n",
              "   'atomic_fact': 'Convinced of her devotion and purity, Charles VII sent Joan of Arc, who was about seventeen years old, to the siege of Orléans as part of a relief army.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'April 1429',\n",
              "    'banner',\n",
              "    'hope',\n",
              "    'French army',\n",
              "    'demoralized'],\n",
              "   'atomic_fact': 'Joan of Arc arrived at the city in April 1429, wielding her banner and bringing hope to the demoralized French army.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'nine days',\n",
              "    'arrival',\n",
              "    'English',\n",
              "    'abandoned',\n",
              "    'siege'],\n",
              "   'atomic_fact': \"Nine days after Joan of Arc's arrival, the English abandoned the siege.\"},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'French',\n",
              "    'aggressively pursue',\n",
              "    'English',\n",
              "    'Loire Campaign',\n",
              "    'decisive victory',\n",
              "    'Patay',\n",
              "    'French army',\n",
              "    'advance',\n",
              "    'Reims',\n",
              "    'unopposed',\n",
              "    'Charles VII',\n",
              "    'crowned',\n",
              "    'King of France',\n",
              "    'Joan of Arc',\n",
              "    'side'],\n",
              "   'atomic_fact': 'Joan of Arc encouraged the French to aggressively pursue the English during the Loire Campaign, which culminated in another decisive victory at Patay, opening the way for the French army to advance on Reims unopposed, where Charles VII was crowned as the King of France with Joan of Arc at his side.'},\n",
              "  {'key_elements': ['victories',\n",
              "    'French morale',\n",
              "    'final triumph',\n",
              "    \"Hundred Years' War\",\n",
              "    'several decades later'],\n",
              "   'atomic_fact': \"These victories boosted French morale, paving the way for their final triumph in the Hundred Years' War several decades later.\"},\n",
              "  {'key_elements': [\"Charles VII's coronation\",\n",
              "    'Joan of Arc',\n",
              "    'unsuccessful',\n",
              "    'siege of Paris',\n",
              "    'September 1429',\n",
              "    'failed',\n",
              "    'siege of La Charité',\n",
              "    'November'],\n",
              "   'atomic_fact': \"After Charles VII's coronation, Joan of Arc participated in the unsuccessful siege of Paris in September 1429 and the failed siege of La Charité in November.\"},\n",
              "  {'key_elements': ['defeats', \"court's faith\", 'Joan of Arc', 'reduced'],\n",
              "   'atomic_fact': \"Her role in these defeats reduced the court's faith in Joan of Arc.\"},\n",
              "  {'key_elements': ['early 1430',\n",
              "    'Joan of Arc',\n",
              "    'company of volunteers',\n",
              "    'relieve',\n",
              "    'Compiègne',\n",
              "    'besieged',\n",
              "    'Burgundians',\n",
              "    'French allies',\n",
              "    'English'],\n",
              "   'atomic_fact': 'In early 1430, Joan of Arc organized a company of volunteers to relieve Compiègne, which had been besieged by the Burgundians—French allies of the English.'},\n",
              "  {'key_elements': ['Joan of Arc', 'captured', 'Burgundian troops', '23 May'],\n",
              "   'atomic_fact': 'Joan of Arc was captured by Burgundian troops on 23 May.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'unsuccessfully',\n",
              "    'escape',\n",
              "    'handed',\n",
              "    'English',\n",
              "    'November'],\n",
              "   'atomic_fact': 'After trying unsuccessfully to escape, Joan of Arc was handed to the English in November.'},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'trial',\n",
              "    'Bishop Pierre Cauchon',\n",
              "    'heresy',\n",
              "    'blaspheming',\n",
              "    \"wearing men's clothes\",\n",
              "    'visions',\n",
              "    'demonic',\n",
              "    'refusing',\n",
              "    'submit',\n",
              "    'judgment',\n",
              "    'church'],\n",
              "   'atomic_fact': \"Joan of Arc was put on trial by Bishop Pierre Cauchon on accusations of heresy, which included blaspheming by wearing men's clothes, acting upon visions that were demonic, and refusing to submit her words and deeds to the judgment of the church.\"},\n",
              "  {'key_elements': ['Joan of Arc',\n",
              "    'guilty',\n",
              "    'burned at the stake',\n",
              "    '30 May 1431',\n",
              "    'nineteen years old'],\n",
              "   'atomic_fact': 'Joan of Arc was declared guilty and burned at the stake on 30 May 1431, aged about nineteen.'}]}"
            ]
          },
          "metadata": {},
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain_community.graphs import Neo4jGraph\n",
        "\n",
        "os.environ[\"NEO4J_URI\"] = \"bolt://34.239.226.242:7687\"\n",
        "os.environ[\"NEO4J_USERNAME\"] = \"neo4j\"\n",
        "os.environ[\"NEO4J_PASSWORD\"] = \"combat-cargo-images\"\n",
        "\n",
        "graph = Neo4jGraph(refresh_schema=False)\n",
        "\n",
        "graph.query(\"\"\"CREATE CONSTRAINT IF NOT EXISTS FOR (c:Chunk) REQUIRE c.id IS UNIQUE\"\"\")\n",
        "graph.query(\"\"\"CREATE CONSTRAINT IF NOT EXISTS FOR (c:AtomicFact) REQUIRE c.id IS UNIQUE\"\"\")\n",
        "graph.query(\"\"\"CREATE CONSTRAINT IF NOT EXISTS FOR (c:KeyElement) REQUIRE c.id IS UNIQUE\"\"\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kShKiVoDrLjk",
        "outputId": "ac08993b-3a35-4047-f4ca-c609a7926736"
      },
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[]"
            ]
          },
          "metadata": {},
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import_query = \"\"\"\n",
        "MERGE (c:Chunk {id: $chunk_id})\n",
        "SET c.text = $chunk_text\n",
        "WITH c\n",
        "UNWIND $atomic_facts AS af\n",
        "MERGE (a:AtomicFact {id: af.id})\n",
        "SET a.text = af.atomic_fact\n",
        "MERGE (c)-[:HAS_ATOMIC_FACT]->(a)\n",
        "WITH c, a, af\n",
        "UNWIND af.key_elements AS ke\n",
        "MERGE (k:KeyElement {id: ke})\n",
        "MERGE (a)-[:HAS_KEY_ELEMENT]->(k)\n",
        "\"\"\"\n",
        "\n",
        "def encode_md5(text):\n",
        "    return md5(text.encode(\"utf-8\")).hexdigest()\n",
        "\n",
        "def extract_and_store(text):\n",
        "    result = construction_chain.invoke({\"input\":text}).dict()\n",
        "    for af in result[\"atomic_facts\"]:\n",
        "        af[\"id\"] = encode_md5(af[\"atomic_fact\"])\n",
        "    text_id = encode_md5(text)\n",
        "    graph.query(import_query, params={\"chunk_id\": text_id, \"chunk_text\": text, \"atomic_facts\": result[\"atomic_facts\"]})"
      ],
      "metadata": {
        "id": "_1oTe3--1PFu"
      },
      "execution_count": 38,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "extract_and_store(text)"
      ],
      "metadata": {
        "id": "jDiIcy9H3njG"
      },
      "execution_count": 39,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "__7YY7jS3pKc"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}